﻿/*
 *	Copyright (c) 2009 Queensland University of Technology. All rights reserved.
 *	The QUT Bioinformatics Collection is open source software released under the 
 *	Microsoft Public License (Ms-PL): http://www.microsoft.com/opensource/licenses.mspx.
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using QUT.Bio.SilverMap;
using QUT.Bio.SilverMap.ObjectModel;
using QUT.Bio.Util;

namespace BlastExplorer.SilverMapDataProducer {
	/// <summary>
	/// Extends the base SilverMap hit class to fit the Blast Explorer application.
	/// </summary>

	public class Hit : QUT.Bio.SilverMap.ObjectModel.Hit {
		public Hit ( IFeature queryFeature, IFeature hitFeature )
			: base( queryFeature, hitFeature ) {
		}

		#region Property: BitScore
		/// <summary>
		/// Get or set the bit score of this hit.
		/// </summary>
		[Displayed]
		public double BitScore {
			get;
			set;
		}
		#endregion

		/// <summary>
		/// Serializes the content of this hit to an xml element. 
		/// </summary>
		/// <returns></returns>

		public XElement ToXml () {

			return new XElement( "Hit",
				new XElement( "QuerySource", ( (Sequence) QueryFeature.ContainingSequence ).Source.ToString() ),
				new XElement( "QueryId", ( (Sequence) QueryFeature.ContainingSequence ).Id ),
				new XElement( "QueryFrom", QueryFeature.Start ),
				new XElement( "QueryTo", QueryFeature.End ),
				new XElement( "QuerySequence", QueryFeature.SequenceData ),
				new XElement( "HitSource", ( (Sequence) HitFeature.ContainingSequence ).Source.ToString() ),
				new XElement( "HitId", ( (Sequence) HitFeature.ContainingSequence ).Id ),
				new XElement( "HitFrom", HitFeature.Start ),
				new XElement( "HitTo", HitFeature.End ),
				new XElement( "HitSequence", HitFeature.SequenceData ),
				new XElement( "EValue", EValue ),
				new XElement( "Identities", base.Identities ),
				new XElement( "Positives", base.Positives ),
				new XElement( "Midline", base.Midline ),
				new XElement( "BitScore", this.BitScore )
			);
		}

		private static SequenceKey GetKey( XElement element, string sourceName, string idName ) {
			XElement sourceElement = element.Element( sourceName );
			XElement idElement = element.Element( idName );
			
			return new SequenceKey( 
				sourceElement == null ? SequenceSource.Genbank : (SequenceSource) Enum.Parse( typeof(SequenceSource), sourceElement.Value ),
				idElement.Value
			);
		}
		
		public static Hit FromXml ( XElement element, ObjectModel model ) {
			SequenceKey queryKey = GetKey( element, "QuerySource", "QueryId" );
			SequenceKey hitKey = GetKey( element, "HitSource", "HitId" );
			ILinearDomain querySeq = model.sequences[queryKey];
			ILinearDomain hitSeq = model.sequences[hitKey];

			IFeature queryFeature = model.features.Add( new DefaultFeature(
				querySeq,
				long.Parse( element.Element( "QueryFrom" ).Value ),
				long.Parse( element.Element( "QueryTo" ).Value ),
				element.Element( "QuerySequence" ).Value
			) );

			IFeature hitFeature = model.features.Add( new DefaultFeature(
				hitSeq,
				long.Parse( element.Element( "HitFrom" ).Value ),
				long.Parse( element.Element( "HitTo" ).Value ),
				element.Element( "HitSequence" ).Value
			) );

			double bitScore = 0.0;

			if ( element.Element( "BitScore" ) != null ) {
				bitScore = double.Parse( element.Element( "BitScore" ).Value );
			}

			return new Hit( queryFeature, hitFeature ) {
				EValue = double.Parse( element.Element( "EValue" ).Value ),
				Identities = long.Parse( element.Element( "Identities" ).Value ),
				Positives = long.Parse( element.Element( "Positives" ).Value ),
				Midline = element.Element( "Midline" ).Value,
				BitScore = bitScore
			};
		}
	}
}
